home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
tvcolor.arc
/
COLORS.ASC
next >
Wrap
Text File
|
1991-08-26
|
14KB
|
310 lines
Turbo Vision Palettes
=====================
Objects in Turbo Vision can be grouped into two broad classes: those
which are descendants of TView (such as TWindow or TButton), and those
which are not (such as TCollection). The difference, of course, is
that objects which are descended from TView (also called "views" or
"view objects") are intended to be displayed on the computer's screen
at some point in their lifetimes. Every descendant of TView contains a
Draw method, which is executed whenever the view needs to redraw
itself. Although every view's Draw method is different, they all share
one characteristic: they call GetColor to determine what on-screen
colors to use when drawing the various parts of the view.
GetColor in turn calls GetPalette, which returns a pointer to the
view's palette. What is a palette? In Turbo Vision, a palette acts as
a translation table. In much the same way that the ASCII code maps
byte values onto characters, a view's palette maps the set of colors
used by the view onto the palette of the view's owner.
Let's look at the palette of the TLabel view as an example.
(It's shown at the end of the description of TLabel in the Turbo
Vision Guide.) We see that the palette has four entries, numbered 1
through 4. TLabel's Draw method knows that when it wants to draw
normal text, it should use color number 1. But it doesn't know what
color number 1 really is, and it doesn't care. It simply calls
GetColor (1) and uses the color that GetColor returns.
GetColor calls GetPalette, which returns a pointer to TLabel's
palette. From the values contained in the palette, GetColor determines
that for TLabel, color number 1 is equivalent to TLabel's owner's
color number 7. GetColor then calls Owner^.GetColor (7); the owner
view then goes through the same procedure, using its own palette to
perform another level of translation, and so on, until the ultimate
owner is reached, which in most Turbo Vision programs is a
TApplication object (or descendant). The TApplication object is the
final color arbiter, and provides all of the views with the actual
video attributes to use.
Let's trace through the TLabel color hierarchy: We've already
determined that TLabel color number 1 maps onto its owner's color
number 7. The description of TLabel's palette in the TV Guide states
that TLabel's palette maps onto the standard dialog palette. This
tells us that TLabel objects are intended to be owned by
(i.e., inserted into) TDialog objects. If we now turn to TDialog's
palette description, we see that color number 7 (called "Label
Normal") is mapped onto TDialog's owner's color number 38. Well,
dialog boxes are usually inserted into the desktop, so let's look at
TDeskTop's palette. When we do that, we see that TDeskTop doesn't have
a palette; this means that TDeskTop doesn't do any color
translation--TDialog's color number 38 "falls through" to TDeskTop's
owner's palette. Well, the desktop is owned by the application, so
we've reached the end of the chain. When TLabel's Draw method wants to
use color number 1, it eventually gets told to use the application's
color number 38.
TApplication's palettes are not shown in the TV Guide, but we can find
them in the file APP.PAS in the TVISION directory. TApplication
actually uses one of three different palettes, depending on whether
the program is being run on a color, black and white, or monochrome
monitor. For the purposes of this example, we'll assume that we're
using a color monitor. If we locate the 38th entry in TApplication's
palette, we find that it is equal to $70. The upper nybble of the byte
gives the background color, and the lower nybble the foreground color,
according to the following table:
0 - black 4 - red 8 - dark gray C - light red
1 - blue 5 - magenta 9 - light blue D - light magenta
2 - green 6 - brown A - light green E - yellow
3 - cyan 7 - light gray B - light cyan F - white
So, we see that a normal label has black text on a light gray
background. All of the other colors may be tracked down in a similar
manner.
What happens if rather than inserting a TLabel into a TDialog, we
insert it into a TWindow? Well, let's follow the mapping, again using
the "Normal Text" color: TLabel color number 1 -> TWindow color number
7 -> TApplication color number 14, 22, or 30, depending on whether the
window is a blue, cyan, or gray window, respectively. These entries
correspond to blue text on gray, blue text on green, or white text on
light gray. Obviously, none of these are the same as the black text on
light gray of a TLabel inserted into a TDialog. This points out a
universal truth of Turbo Vision palettes: If a view is designed to be
inserted into a particular type of owner view, inserting it into a
different type of owner will almost always result in a change in
color.
Anyone who has played around much with Turbo Vision has encountered
the situation where a view is displayed in flashing white text on a
red background. This happens when a call to GetColor is made with a
color number that exceeds the size of the view's palette. For example,
let's see what happens when we insert a TListBox into a TWindow,
rather than a TDialog. (Note: The TV Guide says that TListBox's
palette maps onto the application palette. This is incorrect; it
actually maps onto TDialog's palette.) TListBox has a five-entry
palette which maps onto entries 26 through 29 in its owner's palette.
Well, lo and behold, a TWindow has only eight entries in its
palette--obtaining the 26th entry is impossible. In this situation,
GetColor returns the flashing white on red color to signal the error.
Here is a list of all of the entries in TApplication's palette, along
with the objects that use them:
1 Background (DeskTop)
2 Text Normal (Menu)
3 Text Disabled (Menu)
4 Text Shortcut (Menu)
5 Selected Normal (Menu)
6 Selected Disabled (Menu)
7 Selected Shortcut (Menu)
8 Frame Passive (Blue Window)
9 Frame Active (Blue Window)
10 Frame Icon (Blue Window)
11 ScrollBar Page (Blue Window)
12 ScrollBar Reserved (Blue Window)
13 Scroller Normal Text (Blue Window)
14 Scroller Selected Text (Blue Window)
15 Reserved (Blue Window)
16 Frame Passive (Cyan Window)
17 Frame Active (Cyan Window)
18 Frame Icon (Cyan Window)
19 ScrollBar Page (Cyan Window)
20 ScrollBar Reserved (Cyan Window)
21 Scroller Normal Text (Cyan Window)
22 Scroller Selected Text (Cyan Window)
23 Reserved (Cyan Window)
24 Frame Passive (Gray Window)
25 Frame Active (Gray Window)
26 Frame Icon (Gray Window)
27 ScrollBar Page (Gray Window)
28 ScrollBar Reserved (Gray Window)
29 Scroller Normal Text (Gray Window)
30 Scroller Selected Text (Gray Window)
31 Reserved (Gray Window)
32 Frame Passive (Dialog)
33 Frame Active (Dialog)
34 Frame Icon (Dialog)
35 ScrollBar Page (Dialog)
36 ScrollBar Controls (Dialog)
37 StaticText (Dialog)
38 Label Normal (Dialog)
39 Label Highlight(Dialog)
40 Label Shortcut (Dialog)
41 Button Normal (Dialog)
42 Button Default (Dialog)
43 Button Selected (Dialog)
44 Button Disabled (Dialog)
45 Button Shortcut (Dialog)
46 Button Shadow (Dialog)
47 Cluster Normal (Dialog)
48 Cluster Selected (Dialog)
49 Cluster Shortcut (Dialog)
50 InputLine Normal (Dialog)
51 InputLine Selected (Dialog)
52 InputLine Arrows (Dialog)
53 History Arrow (Dialog)
54 History Sides (Dialog)
55 HistoryWindow ScrollBar page (Dialog)
56 HistoryWindow ScrollBar controls (Dialog)
57 ListViewer Normal (Dialog)
58 ListViewer Focused (Dialog)
59 ListViewer Selected (Dialog)
60 ListViewer Divider (Dialog)
61 InfoPane (Dialog)
62 Reserved (Dialog)
63 Reserved (Dialog)
What about changing colors in Turbo Vision? If all you want to do is
change the color of all instances of an object, say, by making all of
your TButtons cyan instead of green, you've got it easy. You just
change the appropriate entries in TApplication's palette (41 through
46), and you're set.
That was easy. Now, what about creating a new, unique view which is
unlike any predefined Turbo Vision objects? How will we color it?
Let's say we want to insert our new view (call it a TNewView) into a
TDialog, and we want to use two different colors, one for normal text
and one for highlighted text. First, we add two entries to
TApplication's palette (numbers 64 and 65) that will correspond to the
two colors used by our new view. For the purposes of this example,
we'll say we want blue on light gray ($71) for normal text and light
green on light gray ($7A) for highlighted text (assuming a color
monitor). Our TApplication palette will now look like this:
CColor = #$71#$70#$78#$74#$20#$28#$24#$17#$1F#$1A#$31#$31#$1E#$71#$00 +
#$37#$3F#$3A#$13#$13#$3E#$21#$00#$70#$7F#$7A#$13#$13#$70#$7F +
#$00#$70#$7F#$7A#$13#$13#$70#$70#$7F#$7E#$20#$2B#$2F#$78#$2E +
#$70#$30#$3F#$3E#$1F#$2F#$1A#$20#$72#$31#$31#$30#$2F#$3E#$31 +
#$13#$00#$00#$71#$7A; { <- the last two are the new entries }
We must make similar changes in the black & white and monochrome
palettes, of course. Next, since we will be inserting TNewView into a
TDialog, we need to override TDialog's GetPalette method so that it
will supply GetColor with the proper palette:
const
CNewDialog = CDialog + #64#65;
type
TNewDialog = object (TDialog)
function GetPalette: PPalette; virtual;
end;
.
.
.
function TNewDialog.GetPalette: PPalette;
const
P: String[Length (CNewDialog)] = CNewDialog;
begin
GetPalette := @P;
end;
Since we added our two new colors to the end of the standard TDialog
palette, which contains 32 entries, they will be the 33rd and 34th
entries in TNewDialog's palette. Now we have to define our TNewView so
that it maps onto the 33rd and 34th entry of its owner's palette:
const
CNewView = #33#34;
type
TNewView = object (TView)
function GetPalette: PPalette; virtual;
.
.
.
end;
function TNewView.GetPalette: PPalette;
const
P: String[Length (CNewView)] = CNewView;
begin
GetPalette := @P;
end;
There. That wasn't so bad, was it? When TNewView's Draw method asks
for color number 1, it will get color number 64 from TApplication's
palette; similarly, color number 2 leads to TApplication's color
number 65. If we ever want to change the colors of our TNewView
object, we simply change the entries in TApplication's palette.
Okay, let's try something a bit trickier. Let's say we want to insert
a view into an owner which is not of the "correct" type. We already
know that unless we modify the palettes and associated methods, the
colors will come out wrong. The most general solution to the problem
is to define a new object type, as in the previous example. Thus, if
we wanted to insert a TButton into a TWindow, we would define a
descendant of TButton (called TWindowButton, perhaps) and follow the
same steps we performed above to give it a set of colors to use.
In some cases, we don't need to add to TApplication's palette. In the
previous example, if all we want to do is put a button in a window,
and we want the button to look just like an ordinary TButton inserted
into a TDialog, we can use the same TApplication palette entries (41
through 46):
const
CNewWindow = CGrayWindow + #41#42#43#44#45#46;
CWindowButton = #9#10#11#12#13#13#13#14;
type
TNewWindow = object (TWindow)
function GetPalette: PPalette; virtual;
end;
TWindowButton = object (TButton)
function GetPalette: PPalette; virtual;
end;
The GetPalette method code is analogous to that of the previous
example. Now, when TWindowButton.Draw asks for color number 2, it is
mapped to TNewWindow's color number 10, which is mapped to
TApplication's color number 42, just as if it had been a TButton
inserted into a TDialog. Note that I used CGrayWindow as the basis for
CNewWindow's palette. Since a TButton is normally inserted into a
TDialog, two of its colors (44 and 46) use a gray background. If you
wanted to put buttons into cyan or blue windows, you would need to use
the more general method of adding to TApplication's palette, as in the
previous example.
Last but not least, what about objects which can be instantiated with
one of several palettes? TWindow is a good example of this type of
object; you can have windows with blue, gray, or cyan color schemes.
One of TWindow's fields (Palette) is used to indicate which color
scheme GetPalette should return. TWindow.GetPalette might look
something like this:
function TWindow.GetPalette: PPalette;
const
PGray: string[Length (CGrayWindow)] = CGrayWindow;
PCyan: string[Length (CCyanWindow)] = CCyanWindow;
PBlue: string[Length (CBlueWindow)] = CBlueWindow;
begin
case Palette of
wpGrayWindow: GetPalette = @PGray;
wpCyanWindow: GetPalette = @PCyan;
wpBlueWindow: GetPalette = @PBlue;
end;
end;
You can use the same technique with any objects of your own devising.
Well, that's about it for Turbo Vision palettes. Are you thoroughly
confused yet? Just remember: figuring out what color a view is going
to be drawn with is as simple as tracing the color mapping up the
ownership hierarchy, until you reach the TApplication object.
Please direct comments or suggestions to Steve Schafer [71121,1771].